#include "date.h"
#include <sstream>
#include <iomanip>

Date::Date():year(-1),month(-1),day(-1)
{
}

bool Date::is_valid_date() const
{
	bool p_ok=false;
	p_ok=(get_year_min()<=get_year() && get_year_max()>=get_year() && get_month_min()<=get_month() && get_month_max()>=get_month() && get_day_min()<=get_day() && get_day_max()>=get_day());
	return(p_ok);
}

bool Date::is_leap_year() const
{
	bool p_is_leap_year=false;
	if (((0==get_year()%4) && (0!=get_year()%100)) || (0==get_year()%400))
	{
		p_is_leap_year=true;
	}
	else
	{
		p_is_leap_year=false;
	}
	return(p_is_leap_year);
}

int Date::get_days_in_month() const
{
	int days_in_months[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
	int days_in_month=0;
	if(is_leap_year() && 2==get_month())
	{
		days_in_month=29;
	}
	else
	{
		days_in_month=days_in_months[get_month()-1];
	}
	return(days_in_month);
}

int Date::get_year() const
{
	return(year);
}

int Date::get_month() const
{
	return(month);
}

int Date::get_day() const
{
	return(day);
}

int Date::get_year_min() const
{
	return(1860);
}

int Date::get_year_max() const
{
	return(2099);
}

int Date::get_month_min() const
{
	return(1);
}

int Date::get_month_max() const
{
	return(12);
}

int Date::get_day_min() const
{
	return(1);
}

int Date::get_day_max() const
{
	return(get_days_in_month());
}

std::ostream& operator<<(std::ostream &p_out_stream, const Date &p_date)
{
	p_out_stream<<p_date.year<<'-'<<std::setfill('0')<<std::setw(2)<<p_date.month<<'-'<<std::setfill('0')<<std::setw(2)<<p_date.day;
	if(!p_date.is_valid_date())
	{
		throw Date::INVALID_DATE;
	}

	return(p_out_stream);
}
		
std::istream& operator>>(std::istream &p_in_stream, Date &p_date)
{
	std::istringstream* p_s;
	std::string p_string;
	getline(p_in_stream,p_string,'-');
	p_s=new std::istringstream(p_string);
	(*p_s)>>p_date.year;
	delete p_s;
	getline(p_in_stream,p_string,'-');
	p_s=new std::istringstream(p_string);
	(*p_s)>>p_date.month;
	delete p_s;
	getline(p_in_stream,p_string);
	p_s=new std::istringstream(p_string);
	(*p_s)>>p_date.day;
	delete p_s;
	if(!p_date.is_valid_date())
	{
		throw Date::INVALID_DATE;
	}
	return(p_in_stream);
}
